class EventBus {
  constructor(maxListeners) {
    this._events = {};
    this.maxListeners = maxListeners || Infinity;
  }

  on(eventName, fn) {
    if (!eventName || !fn) {
      return;
    }
    const events = (this._events[eventName] = this._events[eventName] || []);
    if (events.length < this.maxListeners) {
      const index = events.findIndex(fn);
      if (index < 0) {
        // 不添加重复事件
        events.push(fn);
      }
    }
    return this;
  }

  once(eventName, fn) {
    // 方式1
    const func = (...args) => {
      fn.apply(this, args);
      this.off(eventName, func);
    };
    this.on(eventName, func);
    // 方式2
    /* 
      绑定事件的时候，使用：
      {
        once: true,
        listener: func
      }
      这样在emit的时候，如果发现once是true，那么就把这个方法移除
      if (listener.once) {
        this.off(eventName, listener.listener)
      }
    */
  }

  off(eventName, listener) {
    const listeners = this._events[eventName];
    if (!listeners) {
      return;
    }
    if (!listener) {
      this._events[eventName] = [];
      return;
    }
    const index = listeners.findIndex((item) => item === listener);
    if (index >= 0) {
      listeners.splice(index, 1);
    }
    return this;
  }

  emit(eventName, ...args) {
    var listeners = this._events[eventName];
    if (!listeners) {
      return;
    }
    listeners.forEach((listerer) => {
      listerer.apply(this, args);
    });
  }
}

const e = new EventBus();
const func1 = (data) => {
  console.log('emit func1', data);
};

const func2 = (data) => {
  console.log('emit func2', data);
};
e.on('func1', func1);
e.once('func2', func2);
e.emit('func1', 11);
e.emit('func2', 22);
setTimeout(() => {
  e.off('func1', func1);
  e.emit('func1', 11);
  e.emit('func2', 22);
}, 1000);
